/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.seguradora.model.repository.impl;

import br.com.seguradora.exception.PersistenciaException;
import br.com.seguradora.model.Associado;
import br.com.seguradora.model.Foto;
import br.com.seguradora.model.Modelo;
import br.com.seguradora.model.Sinistro;
import br.com.seguradora.model.Veiculo;
import br.com.seguradora.model.constant.TipoVeiculo;
import br.com.seguradora.model.repository.TodosSinistros;
import br.com.seguradora.persistence.GerenciadorDeConexao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 *
 * @author Diego
 */
public class TodosSinistrosImpl implements TodosSinistros {

    private Connection conn;
    private PreparedStatement pr;
    private ResultSet rs;

    @Override
    public boolean inserir(Sinistro sinistro) throws PersistenciaException {
        if (sinistro == null) {
            throw new PersistenciaException("Não foi informado o sinistro a cadastrar.");
        }
        boolean sucesso = false;
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("INSERT INTO SINISTRO(ID, DATA, VALOR_PREJUIZO, OBSERVACAO, ID_VEICULO) VALUES(NULL, ?, ?, ?, ?);",
                    Statement.RETURN_GENERATED_KEYS);
            pr.setDate(1, new java.sql.Date(sinistro.getData().getTime()));
            pr.setDouble(2, sinistro.getValorPrejuizo());
            pr.setString(3, sinistro.getObservacao());
            pr.setLong(4, sinistro.getVeiculo().getId());
            int linhas = pr.executeUpdate();
            if (linhas > 0) {
                sucesso = true;
                rs = pr.getGeneratedKeys();
                rs.first();
                long id = rs.getLong(1);
                sinistro.setId(id);

                inserirFotos(sinistro);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível cadastrar o sinistro.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return sucesso;
    }

    @Override
    public boolean atualizar(Sinistro sinistro) throws PersistenciaException {
        if (sinistro == null) {
            throw new PersistenciaException("Não foi informado o sinistro a atualizar.");
        }
        boolean sucesso = false;
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("UPDATE SINISTRO SET VALOR_PREJUIZO=?, DATA=?, ID_VEICULO=?, OBSERVACAO=? WHERE ID=?;");
            pr.setDouble(1, sinistro.getValorPrejuizo());
            pr.setDate(2, new java.sql.Date(sinistro.getData().getTime()));
            pr.setLong(3, sinistro.getVeiculo().getId());
            pr.setString(4, sinistro.getObservacao());
            pr.setLong(5, sinistro.getId());
            int linhas = pr.executeUpdate();
            if (linhas > 0) {
                sucesso = true;
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível atualizar o sinistro.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr);
        }
        return sucesso;
    }

    @Override
    public boolean excluir(Sinistro sinistro) throws PersistenciaException {
        if (sinistro == null) {
            throw new PersistenciaException("Não foi informado o sinistro a excluir.");
        }
        boolean sucesso = false;
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("DELETE FROM SINISTRO WHERE ID=?;");
            pr.setLong(1, sinistro.getId());
            int linhas = pr.executeUpdate();
            if (linhas > 0) {
                pr = conn.prepareStatement("DELETE FROM FOTO_SINISTRO WHERE ID_SINISTRO=?;");
                pr.setLong(1, sinistro.getId());
                pr.executeUpdate();
                sucesso = true;
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível excluir o sinistro.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr);
        }
        return sucesso;
    }

    @Override
    public List<Sinistro> listarTodos(int... limit) throws PersistenciaException {
        List<Sinistro> lista = new ArrayList<Sinistro>();
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("SELECT S.ID, S.VALOR_PREJUIZO, S.DATA, S.OBSERVACAO, V.ID AS ID_VEICULO, V.COR_PREDOMINANTE, V.TIPO, V.PLACA, M.NOME AS MODELO, A.ID AS ID_ASSOCIADO, A.NOME AS NOME_ASSOCIADO FROM SINISTRO S INNER JOIN VEICULO V ON S.ID_VEICULO = V.ID INNER JOIN MODELO M ON V.ID_MODELO = M.ID INNER JOIN ASSOCIADO A ON V.ID_ASSOCIADO = A.ID ORDER BY S.ID DESC LIMIT ?,?;");
            pr.setInt(1, limit[0]);
            pr.setInt(2, limit[1]);
            rs = pr.executeQuery();
            while (rs.next()) {
                Sinistro sinistro = this.criarSinistro(rs);
                lista.add(sinistro);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível listar os sinistros.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return lista;
    }

    private Sinistro criarSinistro(ResultSet rs) throws PersistenciaException {
        Sinistro sinistro = null;
        try {
            sinistro = new Sinistro(rs.getLong("ID"));
            sinistro.setValorPrejuizo(rs.getDouble("VALOR_PREJUIZO"));
            sinistro.setObservacao(rs.getString("OBSERVACAO"));
            sinistro.setData(rs.getDate("DATA") != null ? new Date(rs.getDate("DATA").getTime()) : null);
            Veiculo veiculo = new Veiculo(rs.getLong("ID_VEICULO"));
            veiculo.setCorPredominante(rs.getString("COR_PREDOMINANTE"));
            veiculo.setModelo(new Modelo(rs.getString("MODELO")));
            veiculo.setTipo(TipoVeiculo.valueOf(rs.getString("TIPO")));
            veiculo.setPlaca(rs.getString("PLACA"));
            veiculo.setAssociado(new Associado(rs.getLong("ID_ASSOCIADO"), rs.getString("NOME_ASSOCIADO")));
            sinistro.setVeiculo(veiculo);
        } catch (SQLException sqlex) {
            StringBuilder msg = new StringBuilder("Não foi possível obter os dados do sinistro.");
            msg.append("\nMotivo: ").append(sqlex.getMessage());
            throw new PersistenciaException(msg.toString());
        }
        return sinistro;
    }

    @Override
    public List<Sinistro> listarPeloAssociado(String nome) throws PersistenciaException {
        List<Sinistro> lista = new ArrayList<Sinistro>();
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("SELECT S.ID, S.VALOR_PREJUIZO, S.DATA, S.OBSERVACAO, V.ID AS ID_VEICULO, V.COR_PREDOMINANTE, V.TIPO, V.PLACA, M.NOME AS MODELO, A.ID AS ID_ASSOCIADO, A.NOME AS NOME_ASSOCIADO FROM SINISTRO S INNER JOIN VEICULO V ON S.ID_VEICULO = V.ID INNER JOIN MODELO M ON V.ID_MODELO = M.ID INNER JOIN ASSOCIADO A ON V.ID_ASSOCIADO = A.ID WHERE A.NOME LIKE ? ORDER BY A.NOME");
            pr.setString(1, "%" + nome + "%");
            rs = pr.executeQuery();
            while (rs.next()) {
                Sinistro sinistro = this.criarSinistro(rs);
                lista.add(sinistro);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível listar os sinistros pelo associado.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return lista;
    }

    @Override
    public List<Sinistro> listarPelaPlaca(String placa) throws PersistenciaException {
        List<Sinistro> lista = new ArrayList<Sinistro>();
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("SELECT S.ID, S.VALOR_PREJUIZO, S.DATA, S.OBSERVACAO, V.ID AS ID_VEICULO, V.COR_PREDOMINANTE, V.TIPO, V.PLACA, M.NOME AS MODELO, A.ID AS ID_ASSOCIADO, A.NOME AS NOME_ASSOCIADO FROM SINISTRO S INNER JOIN VEICULO V ON S.ID_VEICULO = V.ID INNER JOIN MODELO M ON V.ID_MODELO = M.ID INNER JOIN ASSOCIADO A ON V.ID_ASSOCIADO = A.ID WHERE V.PLACA=? ORDER BY V.PLACA");
            pr.setString(1, placa);
            rs = pr.executeQuery();
            while (rs.next()) {
                Sinistro sinistro = this.criarSinistro(rs);
                lista.add(sinistro);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível listar os sinistros pela placa.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return lista;
    }

    private void inserirFotos(Sinistro sinistro) throws PersistenciaException {
        try {
            pr = conn.prepareStatement("DELETE FROM FOTO_SINISTRO WHERE ID_SINISTRO=?;");
            pr.setLong(1, sinistro.getId());
            pr.executeUpdate();
            pr = conn.prepareStatement("INSERT INTO FOTO_SINISTRO (ID, IMAGEM, ID_SINISTRO) VALUES (NULL, ?, ?)");
            for (Foto foto : sinistro.getFotosList()) {
                pr.setBytes(1, foto.toByteArray());
                pr.setLong(2, sinistro.getId());
                pr.executeUpdate();
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível inserir as fotos do sinistro.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        }
    }

    @Override
    public void getFotos(Sinistro sinistro) throws PersistenciaException {
        List<Foto> fotosList = new ArrayList<Foto>();
        sinistro.setFotosList(fotosList);
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("SELECT F.ID, F.IMAGEM FROM FOTO_SINISTRO F INNER JOIN SINISTRO S ON F.ID_SINISTRO = S.ID WHERE F.ID_SINISTRO=?");
            pr.setLong(1, sinistro.getId());
            rs = pr.executeQuery();
            while (rs.next()) {
                Foto foto = Foto.valueOf(rs.getBytes("IMAGEM"));
                foto.setId(rs.getLong("ID"));
                sinistro.getFotosList().add(foto);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível buscar as fotos do sinistro.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
    }

    @Override
    public List<Sinistro> listarPeloMes(int mes) throws PersistenciaException {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}
